﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace ICodeShare.UI.Controls
{
    /// <summary>
    /// 角标装饰器，用于给各类控件添加右上角角标显示
    /// </summary>
    public class FastBadgeAdorner : Adorner
    {
        private FastBadge badge;
        private VisualCollection _visuals;

        #region 构造函数

        public FastBadgeAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            _visuals = new VisualCollection(this);
            TranslateTransform tt = new TranslateTransform();
            tt.X = 10;
            tt.Y = -10;
            badge = new FastBadge()
            {
                HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                VerticalAlignment = System.Windows.VerticalAlignment.Top,
               // RenderTransform = tt,
            };
            //这行代码是使用Path=(ZUI:FastBadgeAdorner.Number)的关键代码
            badge.DataContext = adornedElement;

            _visuals.Add(badge);
        }

        #endregion 构造函数

        #region properties

        #region HasBadge

        /// <summary>
        /// 是否添加角标
        /// </summary>
        public static readonly DependencyProperty HasBadgeProperty =
            DependencyProperty.RegisterAttached("HasBadge", typeof(bool),
                typeof(FastBadgeAdorner), new PropertyMetadata(false, HasBadgeChangedCallBack));

        public static bool GetHasBadge(DependencyObject obj)
        {
            return (bool)obj.GetValue(HasBadgeProperty);
        }

        public static void SetHasBadge(DependencyObject obj, bool value)
        {
            obj.SetValue(HasBadgeProperty, value);
        }

        private static void HasBadgeChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if ((bool)e.NewValue)
            {
                if (element != null)
                {
                    var adornerLayer = AdornerLayer.GetAdornerLayer(element);

                    if (adornerLayer != null)
                    {
                        adornerLayer.Add(new FastBadgeAdorner(element as UIElement));
                    }
                    else
                    {
                        //layer为null，说明还未load过（整个可视化树中没有装饰层的情况不考虑）
                        //在控件的loaded事件内生成装饰件
                        element.Loaded += (s1, e1) =>
                        {
                            var adorner = new FastBadgeAdorner(element);
                            AdornerLayer ad = AdornerLayer.GetAdornerLayer(element);
                            if (ad != null)
                            {
                                ad.Add(adorner);
                            }
                        };
                    }
                }
            }
            else
            {
                //装饰件不可用，移除装饰件
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
                if (layer != null)
                {
                    Adorner[] AllAdorners = layer.GetAdorners(element);
                    if (AllAdorners != null)
                    {
                        IEnumerable<Adorner> desAdorners = AllAdorners.Where(p => p is FastBadgeAdorner);
                        if (desAdorners != null && desAdorners.Count() > 0)
                        {
                            desAdorners.ToList().ForEach(p => layer.Remove(p));
                        }
                    }
                }
            }
        }

        #endregion HasBadge

        #region BadgeVisibility 角标是否可见

        /// <summary>
        /// 是否显示角标(FastBadge已经存在，只不过显示不显示的问题)
        /// </summary>
        public static readonly DependencyProperty BadgeVisibilityProperty = DependencyProperty.RegisterAttached(
            "BadgeVisibility", 
            typeof(Visibility),
            typeof(FastBadgeAdorner),
            new PropertyMetadata(Visibility.Collapsed, OnBadgeVisibilityChanged));

        public static Visibility GetBadgeVisibility(DependencyObject obj)
        {
            return (Visibility)obj.GetValue(BadgeVisibilityProperty);
        }

        public static void SetBadgeVisibility(DependencyObject obj, Visibility value)
        {
            obj.SetValue(BadgeVisibilityProperty, value);
        }

        private static void OnBadgeVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FastBadgeAdorner adorner = FastBadgeAdorner.GetAdorner(d);
            if (adorner == null)
            {
                return;
            }

            if ((Visibility)e.NewValue==Visibility.Visible)
            {
                adorner.ShowAdorner();
            }
            else
            {
                adorner.HideAdorner();
            }
        }

        #endregion BadgeVisibility

        #region Badge 角标内容

        /// <summary>
        /// 角标的内容
        /// </summary>
        public static readonly DependencyProperty BadgeProperty = DependencyProperty.RegisterAttached(
            "Badge",
            typeof(object),
             typeof(FastBadgeAdorner),
             new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.AffectsArrange));

        public static object GetBadge(DependencyObject obj)
        {
            return (object)obj.GetValue(BadgeProperty);
        }

        public static void SetBadge(DependencyObject obj, object value)
        {
            obj.SetValue(BadgeProperty, value);
        }

        #endregion

        #region Number 数字

        /// <summary>
        /// 角标显示的数字
        /// </summary>
        public static readonly DependencyProperty NumberProperty =DependencyProperty.RegisterAttached(
            "Number",
            typeof(int),
             typeof(FastBadgeAdorner), 
             new PropertyMetadata(0));

        public static int GetNumber(DependencyObject obj)
        {
            return (int)obj.GetValue(NumberProperty);
        }

        public static void SetNumber(DependencyObject obj, int value)
        {
            obj.SetValue(NumberProperty, value);
        }
        #endregion Number

        #region MinValue 最小值

        /// <summary>
        /// 最小值
        /// </summary>
        public static readonly DependencyProperty MinValueProperty = DependencyProperty.RegisterAttached(
            "MinValue",
            typeof(int),
             typeof(FastBadgeAdorner),
             new PropertyMetadata(0));

        public static int GetMinValue(DependencyObject obj)
        {
            return (int)obj.GetValue(MinValueProperty);
        }

        public static void SetMinValue(DependencyObject obj, int value)
        {
            obj.SetValue(MinValueProperty, value);
        }
        #endregion MinValue

        #region MaxValue 最大值

        /// <summary>
        /// 最大值
        /// </summary>
        public static readonly DependencyProperty MaxValueProperty = DependencyProperty.RegisterAttached(
            "MaxValue",
            typeof(int),
             typeof(FastBadgeAdorner),
             new PropertyMetadata(99));

        public static int GetMaxValue(DependencyObject obj)
        {
            return (int)obj.GetValue(MaxValueProperty);
        }

        public static void SetMaxValue(DependencyObject obj, int value)
        {
            obj.SetValue(MaxValueProperty, value);
        }
        #endregion MaxValue

        #region Mode 角标类型

        /// <summary>
        /// 角标样式
        /// </summary>
        public static readonly DependencyProperty ModeProperty =
       DependencyProperty.RegisterAttached("Mode", typeof(BadgeMode),
           typeof(FastBadgeAdorner), new PropertyMetadata(BadgeMode.UnLimited));

        public static BadgeMode GetMode(DependencyObject obj)
        {
            return (BadgeMode)obj.GetValue(ModeProperty);
        }

        public static void SetMode(DependencyObject obj, BadgeMode value)
        {
            obj.SetValue(ModeProperty, value);
        }
        #endregion Mode

        #region Placement 位置

        /// <summary>
        /// 位置
        /// </summary>
        public static readonly DependencyProperty PlacementProperty =
       DependencyProperty.RegisterAttached("Placement", typeof(BadgePlacementMode),
           typeof(FastBadgeAdorner), new PropertyMetadata(BadgePlacementMode.TopRight));

        public static BadgePlacementMode GetPlacement(DependencyObject obj)
        {
            return (BadgePlacementMode)obj.GetValue(PlacementProperty);
        }

        public static void SetPlacement(DependencyObject obj, BadgePlacementMode value)
        {
            obj.SetValue(PlacementProperty, value);
        }
        #endregion Placement

        #region Background

        /// <summary>
        /// 角标背景色
        /// </summary>
        public static readonly DependencyProperty BackgroundProperty =
            DependencyProperty.RegisterAttached("Background", typeof(Brush), typeof(FastBadgeAdorner), new PropertyMetadata(Brushes.OrangeRed));

        public static Brush GetBackground(DependencyObject obj)
        {
            return (Brush)obj.GetValue(BackgroundProperty);
        }

        public static void SetBackground(DependencyObject obj, Brush value)
        {
            obj.SetValue(BackgroundProperty, value);
        }

        #endregion Background

        #region Foreground

        /// <summary>
        /// 字体色
        /// </summary>
        public static readonly DependencyProperty ForegroundProperty =
            DependencyProperty.RegisterAttached("Foreground", typeof(Brush), typeof(FastBadgeAdorner), new PropertyMetadata(Brushes.White));

        public static Brush GetForeground(DependencyObject obj)
        {
            return (Brush)obj.GetValue(ForegroundProperty);
        }

        public static void SetForeground(DependencyObject obj, Brush value)
        {
            obj.SetValue(ForegroundProperty, value);
        }

        #endregion Foreground

        #region BorderBrush

        /// <summary>
        /// 边框色
        /// </summary>
        public static readonly DependencyProperty BorderBrushProperty =
            DependencyProperty.RegisterAttached("BorderBrush", typeof(Brush), typeof(FastBadgeAdorner), new PropertyMetadata(Brushes.White));

        public static Brush GetBorderBrush(DependencyObject obj)
        {
            return (Brush)obj.GetValue(BorderBrushProperty);
        }

        public static void SetBorderBrush(DependencyObject obj, Brush value)
        {
            obj.SetValue(BorderBrushProperty, value);
        }

        #endregion BorderBrush

        #region BorderThickness 图标边框粗细

        /// <summary>
        ///
        /// </summary>
        public static Thickness GetBorderThickness(DependencyObject element)
        {
            return (Thickness)element.GetValue(BorderThicknessProperty);
        }

        /// <summary>
        ///
        /// </summary>
        public static void SetBorderThickness(DependencyObject element, Thickness value)
        {
            element.SetValue(BorderThicknessProperty, value);
        }

        public static readonly DependencyProperty BorderThicknessProperty =
            DependencyProperty.RegisterAttached(
            "BorderThickness",
            typeof(Thickness),
            typeof(FastBadgeAdorner),
            new FrameworkPropertyMetadata(new Thickness(1)));

        #endregion BorderThickness 图标边框粗细

        #region BadgePadding 内缩进

        /// <summary>
        ///
        /// </summary>
        public static Thickness GetBadgePadding(DependencyObject element)
        {
            return (Thickness)element.GetValue(BadgePaddingProperty);
        }

        /// <summary>
        ///
        /// </summary>
        public static void SetBadgePadding(DependencyObject element, Thickness value)
        {
            element.SetValue(BadgePaddingProperty, value);
        }

        public static readonly DependencyProperty BadgePaddingProperty = DependencyProperty.RegisterAttached(
            "BadgePadding",
            typeof(Thickness),
            typeof(FastBadgeAdorner),
            new FrameworkPropertyMetadata(new Thickness(1, 0, 1, 0), FrameworkPropertyMetadataOptions.AffectsArrange));

        #endregion BadgePadding 图标内缩进

        #endregion properties

        #region 重载方法

        protected override int VisualChildrenCount
        {
            get
            {
                return _visuals.Count;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visuals[index];
        }

        protected override Size MeasureOverride(Size constraint)
        {
            return base.MeasureOverride(constraint);
        }

        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            //badge.Arrange(new Rect(arrangeBounds));
            //return base.ArrangeOverride(arrangeBounds);
            var result = base.ArrangeOverride(arrangeBounds);
           
            if (badge == null) return result;
            badge.Arrange(new Rect(arrangeBounds));
            var containerDesiredSize = badge.DesiredSize;
            if ((containerDesiredSize.Width <= 0.0 || containerDesiredSize.Height <= 0.0)
                && !double.IsNaN(badge.ActualWidth) && !double.IsInfinity(badge.ActualWidth)
                && !double.IsNaN(badge.ActualHeight) && !double.IsInfinity(badge.ActualHeight))
            {
                containerDesiredSize = new Size(badge.ActualWidth, badge.ActualHeight);
            }

            var h = 0 - containerDesiredSize.Width / 2;
            var v = 0 - containerDesiredSize.Height / 2;
            badge.Margin = new Thickness(0);
            badge.Margin = new Thickness(h, v, h, v);

            return result;
        }

        #endregion 重载方法

        #region Private Methods

        private void ShowAdorner()
        {
            badge.Visibility = Visibility.Visible;
        }

        private void HideAdorner()
        {
            badge.Visibility = Visibility.Collapsed;
        }

        private void ShowNormal()
        {
            TranslateTransform tt = new TranslateTransform();
            tt.X = 10;
            tt.Y = -10;
            this.badge.RenderTransform = tt;
            //this.badge.IsDot = false;
        }

        private void SowDot()
        {
            TranslateTransform tt = new TranslateTransform();
            tt.X = 4;
            tt.Y = -4;
            this.badge.RenderTransform = tt;
            //this.badge.IsDot = true;
        }

        private static FastBadgeAdorner GetAdorner(DependencyObject d)
        {
            var element = d as FrameworkElement;

            if (element != null)
            {
                var adornerLayer = AdornerLayer.GetAdornerLayer(element);
                if (adornerLayer != null)
                {
                    //能够获取装饰层，说明已经load过了，直接生成装饰件
                    var adorners = adornerLayer.GetAdorners(element);
                    if (adorners != null && adorners.Count() != 0)
                    {
                        var adorner = adorners.FirstOrDefault() as FastBadgeAdorner;

                        return adorner;
                    }
                }
            }

            return null;
        }

        #endregion Private Methods
    }
}
